/**
 * @Author: zhongyang
 * @Date: 2022/6/24 17:00
 */

package main

import "fmt"

/**
03_抽象工厂模式
概念：提供一个创建一系列相关或互相依赖对象的接口，而无需指定它们具体的类；抽象工厂为工厂方法模式的升级版。
与工厂方法模式的区别：工厂方法模式针对的是一个产品等级结构；而抽象工厂模式则是针对的多个产品等级结构。
*/

// OrderMainDAO 为订单主记录
type OrderMainDAO interface {
	SaveOrderMain()
}

// OrderDetailDAO 为订单详情记录
type OrderDetailDAO interface {
	SaveOrderDetail()
}

// DAOFactory DAO 抽象工厂接口
type DAOFactory interface {
	CreateOrderMainDAO() OrderMainDAO
	CreateOrderDetailDAO() OrderDetailDAO
}

// ============= 这部分为RDB的工厂实现，以及该工厂的产品实现 ================

// RDBMainDAO 为关系型数据库的OrderMainDAO实现
type RDBMainDAO struct {
}

func (r *RDBMainDAO) SaveOrderMain() {
	fmt.Println("rdb main save")
}

// RDBDetailDAO 为关系型数据库的OrderDetailDAO实现
type RDBDetailDAO struct {
}

func (r *RDBDetailDAO) SaveOrderDetail() {
	fmt.Println("rdb detail save")
}

// RDBDAOFactory 是RDB 抽象工厂实现
type RDBDAOFactory struct {
}

func (r *RDBDAOFactory) CreateOrderMainDAO() OrderMainDAO {
	return &RDBMainDAO{}
}

func (r *RDBDAOFactory) CreateOrderDetailDAO() OrderDetailDAO {
	return &RDBDetailDAO{}
}

// ==================================================================

// =================== 这部分为XML的工厂实现以及对应产品实现 ================

type XMLDAOFactory struct {
}

func (x *XMLDAOFactory) CreateOrderMainDAO() OrderMainDAO {
	return &XMLMainDAO{}
}

func (x *XMLDAOFactory) CreateOrderDetailDAO() OrderDetailDAO {
	return &XMLDetailDAO{}
}

type XMLMainDAO struct {
}

func (X XMLMainDAO) SaveOrderMain() {
	fmt.Println("xml main save")
}

type XMLDetailDAO struct {
}

func (X XMLDetailDAO) SaveOrderDetail() {
	fmt.Println("xml detail save")
}

// ======================================================

func main() {
	// 创建RDB工厂
	rdbFactory := &RDBDAOFactory{}
	getMainAndDetail(rdbFactory)

	// 创建XML工厂
	xmlFactory := &XMLDAOFactory{}
	getMainAndDetail(xmlFactory)
}

func getMainAndDetail(factory DAOFactory) {
	factory.CreateOrderMainDAO().SaveOrderMain()
	factory.CreateOrderDetailDAO().SaveOrderDetail()
}
